/*
 *	Copyright 2011 ja4cli
 *
 *	Licensed under the Apache License, Version 2.0 (the "License");
 *	you may not use this file except in compliance with the License.
 *	You may obtain a copy of the License at
 *
 *		http://www.apache.org/licenses/LICENSE-2.0
 *
 *	Unless required by applicable law or agreed to in writing, software
 *	distributed under the License is distributed on an "AS IS" BASIS,
 *	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *	See the License for the specific language governing permissions and
 *	limitations under the License.
 */
package org.skarby.ja4cli;

import org.skarby.ja4cli.internal.Guard;

/**
 * Basis for Parsing arguments from Command line arguments.<p/>
 * 
 * @author askarby
 */
public abstract class ArgumentsParser {
	private final Environment environment;

	public ArgumentsParser(Environment environment) {
		this.environment = environment;
	}
	
	/**
	 * Creates a new instance of the passed configuration class, and populates it, based on the annotations of the class, and the specified arguments.<p/>
	 * 
	 * The configuration class must adhere to the following restrictions:
	 * <ul>
	 * <li>Class must be publicly accessible</li>
	 * <li>Class must have zero-arguments (default) constructor (or no constructors at all)</li>
	 * </ul>
	 * 
	 * If more specific instantiation mechanisms are required, utilize the {@link #parse(Object)}-method instead. 
	 * 
	 * @param configurationClass the type of class to create and inject configuration details into, may <b>not</b> be <code>null</code>.
	 * @param arguments the arguments as delivered by a default <code>public static void main(String[] args)</code>-method, may <b>not</b> be {@link NullPointerException}.
	 * @return a ParseResult containing information about the parsing and the outcome thereof.
	 * @throws ConfigurationParseException if something goes wrong in the process of parsing of the configuration.
	 */
	public <C> ParseResult<C> parse(final Class<C> configurationClass, String[] arguments) throws ConfigurationParseException {
		Guard.isNull(configurationClass, "A configuration class must be specified for instantiation");
		try {
			return parse(configurationClass.newInstance(), arguments);
		} catch (Exception e) {
			throw new ConfigurationInstantiationException(configurationClass, e);
		}
	}
	
	/**
	 * Populates the configuration class, based on the annotations of the class, and the specified arguments.<p/>
	 * 
	 * @param configuration the class to inject configuration details into.
	 * @param arguments the arguments as delivered by a default <code>public static void main(String[] args)</code>-method, may <b>not</b> be {@link NullPointerException}.
	 * @return a ParseResult containing information about the parsing and the outcome thereof.
	 * @throws ConfigurationParseException if something goes wrong in the process of parsing of the configuration.
	 */
	public <C> ParseResult<C> parse(final C configuration, String[] arguments) throws ConfigurationParseException {
		Guard.isNull(configuration, "A configuration must be supplied for being populated with arguments");
		Guard.isNull(arguments, "Arguments must be supplied for the population of the configuration");
		return parse(configuration, environment, arguments);
	}
	
	/**
	 * Performs the actual task of parsing the configuration, and producing the {@link ParseResult}.
	 * @param configuration the class to inject configuration details into, may <b>not</b> be <code>null</code>.
	 * @param environment details about the {@link Environment} the configuration is parsed upon, may <b>not</b> be <code>null</code>.
	 * @param arguments the arguments as delivered by a default <code>public static void main(String[] args)</code>-method, may <b>not</b> be {@link NullPointerException}.
	 * @return a ParseResult containing information about the parsing and the outcome thereof.
	 * @throws ConfigurationParseException if something goes wrong in the process of parsing in the configuration.
	 */
	protected abstract <C> ParseResult<C> parse(final C configuration, final Environment environment, final String[] arguments ) throws ConfigurationParseException;
}
